/**************************************************************************
 *         Copyright(c) 2007 by Sunplus mMedia  Technology Co., Ltd.       *
 *                                                                         *
 *  This software is copyrighted by and is the property of Sunplus mMedia  *
 *  Technology Co., Ltd. All rights are reserved by Sunplus mMedia Techno- *
 *  logy Co., Ltd. This software may only be used in accordance with the   *
 *  corresponding license agreement. Any unauthorized use, duplication,    *
 *  distribution, or disclosure of this software is expressly forbidden.   *
 *                                                                         *
 *  This Copyright notice "M U S T" not be removed or modified without     *
 *  prior written consent of Sunplus mMedia Technology  Co., Ltd.          *
 *                                                                         *
 *  Sunplus mMedia Technology Co., Ltd. reserves the right to modify this  *
 *  software without notice.                                               *
 *                                                                         *
 *  Sunplus mMedia Technology Co., Ltd.                                    *
 *  19-1, Innovation First Road, Science-Based Industrial Park,            *
 *  Hsin-Chu, Taiwan, R.O.C.                                               *
 *                                                                         *
 **************************************************************************/

/**
 * @file		app_ui_power.c
 * @brief		power control
 * @author
 * @since		2008-02-23
 * @date		2008-02-23
 */
#include "general.h"

#include "solution.h"
#include "initio.h"
#include "os_msg.h"
#include "cardlink.h"
#include "storage.h"
#include "main.h"
#include "gpio.h"
#include "gpio_api.h"
#include "key_scan.h"
#include "usbmsdc2.h"
#include "uiflow.h"
#include "exifhdr.h"
#include "exiffunc.h"
#include "dos32.h"

#include "sp1k_aud_api.h"
#include "sp1k_rsvblk_api.h"
#include "sp1k_pb_api.h"
#include "sp1k_osd_api.h"
#include "sp1k_disp_api.h"
#include "sp1k_pv_api.h"
#include "sp1k_snap_api.h"
#include "sp1k_video_api.h"
#include "sp1k_hal_api.h"
#include "sp1k_util_api.h"
#include "sp1k_hal_api.h"
#include "sp1k_vfs_api.h"
#include "sp1k_aaa_api.h"

#include "app_menu_tab.h"
#include "app_ui_osd.h"
#include "app_osd_icon.h"
#include "app_usb.h"
#include "app_still_play.h"
#include "app_audio_play.h"
#include "app_battery.h"
#include "app_ui_power.h"
#include "app_ui_para.h"
#include "app_menu_micro.h"
#include "app_main.h"
#include "app_battery.h"
#include "asicreg.h"

/**************************************************************************
 *                           C O N S T A N T S                            *
 **************************************************************************/
//#define NOT_POWER_OFF
/**************************************************************************
 *                              M A C R O S                               *
 **************************************************************************/

/**************************************************************************
 *                          D A T A    T Y P E S                          *
 **************************************************************************/

/**************************************************************************
 *                         G L O B A L    D A T A                         *
 **************************************************************************/
xdata UINT8 G_NandAlreadyMount = 0;
xdata UINT32 G_AutoOffTime;
xdata UINT32 G_AutoOffReloadTime = 6000;
xdata UINT8  G_AutoOffEn = AUTO_POWEROFF_ENABLE;

/* For indicate SD card has been plug in or plug out */
xdata UINT8 G_SDCardPlugInOut = 0;

UINT8 xdata G_SDCardPlug = 0xFF;//1:plugged in  0:no card
static powerBatLv_t xdata G_BatteryLevel = POWER_BAT_FULL;
panelStatus_t xdata G_PanelStatus = PANEL_STATUS_LCD;//0:LCD  1:NTSC  2:PAL

/**************************************************************************
 *                 E X T E R N A L    R E F E R E N C E S                 *
 **************************************************************************/
//extern xdata UINT8 OsdMaxX;
//extern xdata UINT8 OsdMaxY;
//extern xdata UINT8 OsdMaxNum;

extern xdata UINT8 G_PCCAM;

extern xdata UINT8 rcdFinish;
extern xdata UINT8 exifVlcAtOdd;
extern UINT8 TV_Open;         
/**************************************************************************
 *               F U N C T I O N    D E C L A R A T I O N S               *
 **************************************************************************/
extern void sp1kDispPnlOpen(UINT8);

//-----------------------------------------------------------------------------
//appPwrOffBGShow
//-----------------------------------------------------------------------------
/**
 * @brief	power off background show
 * @param	none
 * @retval	void
 * @see
 * @author	wei.sun
 * @since	2008-04-03
 * @todo
 * @bug
*/
void appPwrOffBGShow(void)
{
	UINT32 srcAdd;
	UINT32 dstAdd;
	UINT8 xShow,yShow;
	UINT8 str[] = "Good Bye";
	UINT8 OsdMaxX, OsdMaxY;
	UINT8 resID = 0x0d; /* the same as start up image */

	sp1kOsdLayoutAttrGet(&OsdMaxX, &OsdMaxY);

	xShow=OsdMaxX/2-3;
	yShow=OsdMaxY-2;
	if(appPanelTypeGet()==0){
		yShow=OsdMaxY-1;
	}
	srcAdd=K_SDRAM_PreviewBufAddrD-2*(320L*240L);//mantis #26146
	dstAdd=srcAdd-3*(320L*240L);

	sp1kHalCdspImgSrcSel(1);
	sp1kHalFrontInputGate(0x11);
	sp1kHalCamModeSet(CAM_MODE_IDLE);

	sp1kHalCdspImgSrcSel(1);

	appBGImgDec(resID, NULL, srcAdd, dstAdd, 1);
	sp1kDispImgShow(dstAdd, (UINT16)320, (UINT16)240, 100);

	sp1kOsdClear(ID_ICON_NONE, 0);
	xShow=OsdMaxX/2-4;
	sp1kOsdStrDraw(xShow, yShow, str, 0);
}

//-----------------------------------------------------------------------------
//appPowerOffProc
//-----------------------------------------------------------------------------
/**
 * @brief	power off flow
 * @param	none
 * @retval	void
 * @see
 * @author
 * @since	2008-02-23
 * @todo
 * @bug
*/
void appPowerOffProc(void)
{
	//here add power off flow
	sp1kTimer1Stop();//add for self snap@wei.sun 20080414
	//printf(" : power off\n");
	//printf("wrt udf\n");
	appUDFSave();
	#ifdef NOT_POWER_OFF
	return;
	#endif
	appPwrOffBGShow();
	//printf("wrt udf END\n");
	//20080327 suny add  start
	appVoicePlay(SP1K_MSG_UNKNOWN, VOICE_TYPE_CLOSE, VOICE_PLAYLEVLE_LOW);
	sp1kHalWait(2000);//mantis:27691
/* 20080611 mattwang modify, because use new disp drv. */
#if 1  /* new. */
	sp1kDispPowerOff(sp1kDispDevActGet());
#else  /* old. */
	sp1kHalPanelOff();
#endif
	//20080327 suny add  end
	printf("zhenglei....off 2\n");
	appPowerShutDown();
}

//-----------------------------------------------------------------------------
//appPowerShutDown
//-----------------------------------------------------------------------------
/**
 * @brief	shut down power supply
 * @param	none
 * @retval	void
 * @see
 * @author	phil.lin
 * @since	2008-02-23
 * @todo
 * @bug
*/
void appPowerShutDown(void)
{
	UINT8 status;
	#ifdef NOT_POWER_OFF
	return;
	#endif
	printf("Off!\n");
	sp1kPWR_HoldCfg();
	sp1kPWR_HoldSet(0);
	ENTER_CRITICAL( status );
	while(1);
}

//-----------------------------------------------------------------------------
//appAutoOffTimeReload
//-----------------------------------------------------------------------------
/**
 * @brief	reload auto off time
 * @param	none
 * @retval	void
 * @see
 * @author
 * @since	2008-02-23
 * @todo
 * @bug
*/
void appAutoOffTimeReload(void)
{
	//here add time reload code
	G_AutoOffTime = G_AutoOffReloadTime;
	//printf("G_AutoOffTime = %ld\n",G_AutoOffTime);
}

//-----------------------------------------------------------------------------
//appAutoOffTimeSet
//-----------------------------------------------------------------------------
/**
 * @brief	set auto off time from menu
 * @param	none
 * @retval	void
 * @see
 * @author
 * @since	2008-02-23
 * @todo
 * @bug
*/
UINT8 appAutoOffTimeSet(void)
{
	uiPara_t* uiPara;

	uiPara = appUiParaGet();

	switch(uiPara->SleepTime)
	{
		case POWER_SAVE_1MIN:
			//printf(" : SAVE 1MIN\n");
			G_AutoOffReloadTime = 6000;
			break;
		case POWER_SAVE_3MIN:
			//printf(" : SAVE 3MIN\n");
			G_AutoOffReloadTime = 18000;
			break;
		case POWER_SAVE_5MIN:
			//printf(" : SAVE 5MIN\n");
			G_AutoOffReloadTime = 30000;
			break;
		default:
			//printf(" : SAVE DEFT\n");
			G_AutoOffReloadTime = 18000;
			break;
	}
	appAutoOffTimeReload();//2008-5-7 add for mantis 24152
	return SUCCESS;
}

//-----------------------------------------------------------------------------
//appAutoOffEn
//-----------------------------------------------------------------------------
/**
 * @brief	enable/disable auto power off
 * @param	none
 * @retval	void
 * @see
 * @author	jintao.liu
 * @since	2008-04-29
 * @todo
 * @bug

input:
 En=AUTO_POWEROFF_ENABLE       Enable Auto Off
 En=AUTO_POWEROFF_DISABLE      Disable Auto Off
*/
void appAutoOffEn(UINT8 En)
{
	G_AutoOffEn = En;
	appAutoOffTimeReload();
}


//-----------------------------------------------------------------------------
//appUDFSave
//-----------------------------------------------------------------------------
/**
 * @brief	save User Define Parameters to nand
 * @param	none
 * @retval	void
 * @see
 * @author	jintao.liu
 * @since	2008-02-23
 * @todo
 * @bug
*/
void appUDFSave(void)
{
	uiPara_t* tempUiPara;
	//uiPara_t testuipara;
	//uiPara_t* test = &testuipara;
	UINT8 i;

	tempUiPara = appUiParaGet();
	tempUiPara->Checksum = 0;
	//add checksum to ui parameters
	//simply add every ui para to checksum
	for( i=0; i<(sizeof(uiPara_t) - 4); i++)
	{
		(tempUiPara->Checksum) += *(((UINT8 *)tempUiPara + i));
	}

	//save ui parameters to nand
	sp1kNandRsvWrite(0x80, ((K_SDRAM_ShadowAddr + K_SDRAM_ShadowSize) << 1) - 0x1000UL);
	//	printf("add is %lx\n", ((K_SDRAM_ShadowAddr + K_SDRAM_ShadowSize) << 1) - 0x200UL);
}

//-----------------------------------------------------------------------------
//appUDFLoad
//-----------------------------------------------------------------------------
/**
 * @brief	load User Define Parameters to struct
 * @param	none
 * @retval	0:check sum ok ,load ui para from nand
 			1:check sum err,load default ui para
 * @see
 * @author	jintao.liu
 * @since	2008-02-23
 * @todo
 * @bug
*/
UINT8 appUDFLoad(void)
{
	sp1kNandRsvRead(0x80, ((K_SDRAM_ShadowAddr + K_SDRAM_ShadowSize) << 1) - 0x1000UL);
//	printf("add is %lx\n", ((K_SDRAM_ShadowAddr + K_SDRAM_ShadowSize) << 1) - 0x200UL);
	return appUDFCheckSum();
#if	0
	checksum = 0;
	for( i=0; i<(sizeof(uiPara_t) - 4); i++)
	{
		checksum += *(((UINT8 *)ptestUiPara + i));
	}

	if(checksum == ptestUiPara->Checksum)//checksum equal
	{
		//load ui para from nand to ui struct
		appUiParaInit(PARA_INIT_FROM_UDF);
		return 0;
	}
	else//checksum error
	{
		appUiParaInit(PARA_INIT_WITH_DEF);//ui para load default
		return 1;
	}
#else
	return 0;
#endif
}

//-----------------------------------------------------------------------------
//appUDFCheckSum
//-----------------------------------------------------------------------------
/**
 * @brief	load User Define Parameters to struct
 * @param	none
 * @retval	0:check sum ok ,load ui para from nand
 			1:check sum err,load default ui para
 * @see
 * @author	jintao.liu
 * @since	2008-02-23
 * @todo
 * @bug
*/
UINT8 appUDFCheckSum(void)
{
	uiPara_t* ptestUiPara;
	UINT32 checksum;
	UINT8 i;

	ptestUiPara = appUiParaGet();

	checksum = 0;
	for( i=0; i<(sizeof(uiPara_t) - 4); i++)
	{
		checksum += *(((UINT8 *)ptestUiPara + i));
	}

	if(ptestUiPara->SunplusFlag[0]=='S'&&ptestUiPara->SunplusFlag[1]=='U'&&ptestUiPara->SunplusFlag[2]=='N'&&ptestUiPara->SunplusFlag[3]=='P')
	{
		if(checksum != ptestUiPara->Checksum)//checksum err
		{
			return FAIL;
		}
		else//check sum ok
		{
			return SUCCESS;
		}
	}
	else{
		return FAIL;
	}
}

//-----------------------------------------------------------------------------
//appBatLvGet
//-----------------------------------------------------------------------------
/**
 * @brief	get battery level
 * @param	none
 * @retval	none
 * @see
 * @author	jintao.liu
 * @since	2008-02-23
 * @todo
 * @bug
*/
//powerBatLv_t* appBatLvGet(void)
//{
//	return &G_BatteryLevel;
//}
void appBatLvGet(powerBatLv_t* batlv)
{
	scanTag_t* pAdcHdl;

	sp1kAdcHdlGet(&pAdcHdl);

	*batlv = pAdcHdl->battAdc.battLvl;
	//printf("Lv(%bu)\n", *batlv);
	//*batlv = G_BatteryLevel;
}

//-----------------------------------------------------------------------------
//appTVOutDetect
//-----------------------------------------------------------------------------
/**
 * @brief	detect tv plug in plug out
 * @param	none
 * @retval	none
 * @see
 * @author	jintao.liu
 * @since	2008-02-23
 * @todo
 * @bug
*/
extern UINT8 G_UI_USBConnect;
void appTVOutDetect(void)
{
	static UINT8 plugOut = 0xFF;
	static UINT8 tvStatus = 0xFF;
	static UINT8 time = 0;
	static UINT8 tvMode = 0xFF;
	UINT8 mode;
	uiPara_t* uiPara;
	devAttr_t* devAttr;
	UINT8 sts;


	if ( plugOut == sp1kTV_PlugGet() ) {
		time++;
	}
	else {
		plugOut = sp1kTV_PlugGet();
		time = 0;
		return;
	}

	if ( time < 3 ) {
		return;//detect 3 times to avoid dithering
	}

	if ( (appPanelTypeGet() == plugOut) && (0xFF != G_PanelStatus) ) { //suny add for insert TV open
		uiPara = appUiParaGet();
		if ( uiPara->TVMode == TVMODE_NTSC ) {
			G_PanelStatus= PANEL_STATUS_NTSC;
		}
		else if ( uiPara->TVMode == TVMODE_PAL ) {
			G_PanelStatus= PANEL_STATUS_PAL;
		}
		//return;
	}

	sts = appCurrStateGet();
	uiPara = appUiParaGet();
	devAttr = sp1kDevHdlGet();
	if ( tvStatus != plugOut || (!plugOut && tvMode != uiPara->TVMode) ) {
		if ( !plugOut ) {  /* tv plug in. */
			if ( sts != APP_STATE_POWER_ON ) {
				//Panel = TV , so estimate ntsc/pal
				if ( uiPara->TVMode == TVMODE_NTSC ) {
					mode = PANEL_STATUS_NTSC;
					devAttr[DEV_ID_TV].devType = DEV_TYPE_TV_NTSC;
				}
				else {
					mode = PANEL_STATUS_PAL;
					devAttr[DEV_ID_TV].devType = DEV_TYPE_TV_PAL;
				}
				tvMode = uiPara->TVMode;

				devAttr[DEV_ID_TV].devEn = 1;
				devAttr[DEV_ID_TV].devSts = DEV_STS_CONNECTED;
				devAttr[DEV_ID_PANEL].devEn = 0;
				devAttr[DEV_ID_PANEL].devSts = DEV_STS_CONNECTED;
			}
			osMsgPost(SP1K_MSG_TV_PLUG_IN);
		}
		else {  /* tv plug out. */
			if ( sts != APP_STATE_POWER_ON ) {
				mode = PANEL_STATUS_LCD;
				devAttr[DEV_ID_TV].devEn = 0;
				devAttr[DEV_ID_TV].devSts = DEV_STS_DISCONNECTED;
				devAttr[DEV_ID_PANEL].devEn = 1;
				devAttr[DEV_ID_PANEL].devSts = DEV_STS_CONNECTED;
			}
		}

		if ( sts != APP_STATE_POWER_ON ) {
			if ( plugOut && tvStatus != 0xFF ) {
				osMsgPost(SP1K_MSG_TV_PLUG_OUT);
			}
			else {   
				if(appPreStateGet(0) == APP_STATE_POWER_ON){
					if(plugOut && TV_Open) {
						osMsgPost(SP1K_MSG_TV_PLUG_OUT);
						TV_Open=0;
					}
					
				}
			}
			tvStatus = plugOut;
		}

		if ( G_PanelStatus != mode ) {
			if(G_PCCAM ==1){
				G_PCCAM = 0;
				sp1kUsbPccamStop();
				TIMER0_Start();
			}
			G_PanelStatus = mode;
			appAutoOffTimeReload();//jintao.liu 2008-4-29 auto power off
			printf("Panel Chg!\n");
		}
	}
}

//-----------------------------------------------------------------------------
//appPanelTypeGet
//-----------------------------------------------------------------------------
/**
 * @brief	get panel type
 * @param	none
 * @retval	1: LCD, 0: TV
 * @see
 * @author	sunyong
 * @since	2008-02-23
 * @todo
 * @bug
*/
UINT8 appPanelTypeGet(void)
{
	devAttr_t* devAttr;

	devAttr = sp1kDevHdlGet();
	return devAttr[DEV_ID_PANEL].devEn;
}

//-----------------------------------------------------------------------------
//appPanelStatusGet
//-----------------------------------------------------------------------------
/**
 * @brief	get panel status
 * @param	none
 * @retval	none
 * @see
 * @author	jintao.liu
 * @since	2008-02-23
 * @todo
 * @bug
*/
void appPanelStatusGet(panelStatus_t* panelMode)
{
	//return &G_BatteryLevel;
	*panelMode = G_PanelStatus;
}

void appPanelStatusSet(panelStatus_t panelMode)
{
	//return &G_BatteryLevel;
	//*panelMode = G_PanelStatus;
	G_PanelStatus = panelMode;
}

//-----------------------------------------------------------------------------
//appDispSet
//-----------------------------------------------------------------------------
/**
 * @brief		panel select
 * @param	none
 * @retval	none
 * @see
 * @author	yong.sun
 * @since	2008-02-23
 * @todo
 * @bug
*/
void appDispSet(void)
{
	panelStatus_t pnl;
	UINT16 hSize,vSize;
	UINT8 status;
	devAttr_t* devAttr;
	uiPara_t* puiPara;

	rcdFinish = 1;
	puiPara = appUiParaGet();
	appPanelStatusGet(&pnl);
	devAttr = sp1kDevHdlGet();
	switch(pnl){
		case PANEL_STATUS_LCD:
			printf("LCD\n");
			sp1kAudioVolumeSet(puiPara->Volume);
			sp1kDispPnlOpen(1);
			sp1kDispImgWinEn(1);
			devAttr[DEV_ID_PANEL].devSts = DEV_STS_RDY;
			break;
		case PANEL_STATUS_NTSC:
			printf("NTSC\n");
			sp1kAudioVolumeSet(puiPara->Volume);
			sp1kDispPnlOpen(2);
			devAttr[DEV_ID_TV].devSts = DEV_STS_RDY;
			break;
		case PANEL_STATUS_PAL:
			printf("PAL\n");
			sp1kAudioVolumeSet(puiPara->Volume);
			sp1kDispPnlOpen(3);
			devAttr[DEV_ID_TV].devSts = DEV_STS_RDY;
			break;
		default:
			break;
	}
	sp1kOsdInit(appPanelTypeGet());

	status = appCurrStateGet();
	switch(status) {
		case APP_STATE_STILL_VIEW:
			sp1kPvSizeGet(&hSize, &vSize);
			break;
		case APP_STATE_STILL_PLAY:
		case APP_STATE_MUTI_PLAY:
			sp1kPbDecodeSizeGet(&hSize, &vSize);
			break;
		case APP_STATE_VIDEO_VIEW:
			sp1kPvSizeGet(&hSize, &vSize);
			break;
		case APP_STATE_VIDEO_PLAY:
			sp1kVideoPbSizeGet(&hSize, &vSize);
			break;
		default:
			hSize = 320;
			vSize = 240;
			break;
	}
	//printf("h: %u v:%u\n", hSize, vSize);

	sp1kHalDispScaleSet(hSize,vSize,100);

	switch(status) {
		case APP_STATE_STILL_VIEW:
			appStillOsdInit();
			break;
		case APP_STATE_STILL_PLAY:
			appStillPlayInit(1);
			break;
		case APP_STATE_MUTI_PLAY:
			sp1kPbMultiPlayObjFrameDraw(pbFile.dwIndex, 1);
			break;
		case APP_STATE_VIDEO_VIEW:
			appVideoOsdInit();
			break;
		case APP_STATE_AUDIO_REC:
			appAudioOsdInit();
			break;
		case APP_STATE_USB:
			appUSBBGShow();
			break;
		case APP_STATE_MENU:
			switch(appPreStateGet(0)) {
				case APP_STATE_STILL_VIEW:
					appStillOsdInit();
					break;
				case APP_STATE_STILL_PLAY:
					appStillPlayInit(1);
					break;
				case APP_STATE_VIDEO_VIEW:
					appVideoOsdInit();
					break;
				default:
					appStillOsdInit();
					break;
			}
			break;
		default:
			appStillOsdInit();
			break;
	}

	if ( pnl == PANEL_STATUS_LCD ) {
		sp1kDispPowerOn(sp1kDispDevActGet());
	}
	sp1kHalCtrlScreen(3);
}

//-----------------------------------------------------------------------------
//appSDPlugAction
//-----------------------------------------------------------------------------
/**
 * @brief	SD plug action
 * @param	none
 * @retval	none
 * @see
 * @author	jintao.liu
 * @since	2008-02-23
 * @todo
 * @bug
*/
void appSDPlugAction(void)
{
	UINT8 value;
	devAttr_t* devAttr;

	//sp1kSD_CdCfg();
	value = sp1kSD_CdGet();
	//value = 0 , card plug in
	//value != 0 , card plug out
	if (G_SDCardPlug != value)
	{
		G_SDCardPlugInOut = 0x01;
		devAttr = sp1kDevHdlGet();

		G_SDCardPlug = value;
		appAutoOffTimeReload();//jintao.liu 2008-4-29 auto power off
		if(value == 0)//card insert
		{
			devAttr[DEV_ID_CARD].devEn = 1;
			devAttr[DEV_ID_CARD].devSts = DEV_STS_CONNECTED;
			devAttr[DEV_ID_CARD].devType = DEV_TYPE_CARD_SD;
			devAttr[DEV_ID_DISK].devEn = 0;
			devAttr[DEV_ID_DISK].devSts = DEV_STS_CONNECTED;
			osMsgPost(SP1K_MSG_CARD_PLUG_IN);
			printf("SD card Insert!\n");
		}
		else
		{
			devAttr[DEV_ID_CARD].devEn = 0;
			devAttr[DEV_ID_CARD].devSts = DEV_STS_DISCONNECTED;
			devAttr[DEV_ID_DISK].devEn = 1;
			devAttr[DEV_ID_DISK].devSts = DEV_STS_CONNECTED;
			if (DOS_DosRamStsGet() == TRUE) {
				devAttr[DEV_ID_DISK].devType = DEV_TYPE_DISK_DRAM;
			} else {
				devAttr[DEV_ID_DISK].devType = DEV_TYPE_DISK_NAND;
			}
			osMsgPost(SP1K_MSG_CARD_PLUG_OUT);
			printf("SD card Eject!\n");
		}
	}
}

//-----------------------------------------------------------------------------
//appSDPlugStatusGet
//-----------------------------------------------------------------------------
/**
 * @brief	SD plug status get
 * @param	none
 * @retval	  1:card     0:no card
 * @see
 * @author	jintao.liu
 * @since	2008-02-23
 * @todo
 * @bug
*/
//return 1:card inserted
//		 2:no card
UINT8 appSDPlugStatusGet(void)
{
	if(G_SDCardPlug ==0)//card insert
	{
		return 1;
	}
	else
	{
		return 0;
	}
}

//-----------------------------------------------------------------------------
//appSDProtectStatusGet
//-----------------------------------------------------------------------------
/**
 * @brief	SD protection status get
 * @param	none
 * @retval	0:no protect     1:Write protect
 * @see
 * @author	jintao.liu
 * @since	2008-02-23
 * @todo
 * @bug
*/
//return  0:no protect     1:Write protect
UINT8 appSDProtectStatusGet(void)
{
	UINT8 ProtStatus;

	if(0 == appSDPlugStatusGet())//No sd
	{
		ProtStatus = 0;
	}
	else
	{
		ProtStatus = sp1kSDWriteProtectDetectGet();
	}

	#if(_HW_SOLUTION_ == _HW_EVB_)
	ProtStatus = 0;
	#endif

	return ProtStatus;
}

void appSdPowerRecycle(void)
{
	UINT16 i;
	UINT8 byteId, bitMsk;


	/* do SD power recycle */
	sp1kHalFlashModeSet(K_MEDIA_NONE, K_MEDIA_NONE, 0x01);  // set media type to gpio.
	gpioByteDirSet(GPIO_BYTE_FM1, 0x3F, 0x3E);  // set fmgpio[9:5] as output, and fmgpio[4] as input.
	gpioByteOutSet(GPIO_BYTE_FM1, 0x3E, 0x00);  // set fmgpio[9:5] to low.
	pkgDedicateGpioGet(PKG_DEDICATE_PIN_MLC_SDPWRCTL, &byteId, &bitMsk);
	gpioByteDirSet(byteId, bitMsk, 0xFF);  // set card detect pin as output.
	gpioByteOutSet(byteId, bitMsk, 0xFF);  // set card detect pin to high.
	for( i = 0; i< 1000; i ++){/* it's about 200ms */
		DELAY_1ms();
	}
	gpioByteOutSet(byteId, bitMsk, 0x00);  // set card detect pin to low.
	sp1kTimeDelay1ms();
	gpioByteDirSet(GPIO_BYTE_FM1, 0x3F, 0x00);  // set fmgpio[9:4] as input.
	sp1kHalFlashModeSet(K_MEDIA_SDF,K_MEDIA_NANDF, 0x01);
	for( i = 0; i< 500; i ++){/* it's about 100ms */
		DELAY_1ms();
	}
	sp1kSD_CdCfg();/* set detect pin as input pin again */
}

//-----------------------------------------------------------------------------
//appSDPlugAction
//-----------------------------------------------------------------------------
/**
 * @brief	SD plug action
 * @param	none
 * @retval	none
 * @see
 * @author	jintao.liu
 * @since	2008-02-23
 * @todo
 * @bug
*/
UINT8 xdata  storageReadyflag;
extern xdata UINT32 G_Card_TotalCardSize;
void appStorageMount (UINT8 type) USING_0
{
	UINT32 sts=FALSE;
	UINT8 tmp = IE, retry;
	devAttr_t* devAttr;

	retry = 0;
	IE = 0x81;
	Card_InitRam();
	Card_InitGlobal();
	G_Card_Type = type;
	
	if (DOS_DosRamStsGet() == TRUE) {
		
#if 1 //mark off here will mount nand
		G_NandAlreadyMount |= 0x01;
		if(type == K_MEDIA_NANDF){
			//Not to mount Nand but DOS DRAM
			type = K_MEDIA_DOSRAM;
			G_Card_Type = type;
		}
#endif
		if((G_NandAlreadyMount & 0x02) != 0x02){
			G_Card_Type = K_MEDIA_DOSRAM;
			G_ucStorageType = 0xff;
			G_NandAlreadyMount |= 0x2;
			sts = sp1kVfsInit(1);
				if( sts != TRUE ){
				sp1kVfsFmt(1);
				sp1kVfsInit(0);
			}
			G_Card_Type = type;
		}
	}

#ifdef DOS32_SUPPORT

	/* add by phil for disk driver lib release s*/
	devAttr = sp1kDevHdlGet();
	devAttr += DEV_ID_DISK;
	if (devAttr->devType == DEV_TYPE_DISK_NAND) {
		//First Initial Nand
		if((type != K_MEDIA_NANDF) && ((G_NandAlreadyMount & 0x01) != 0x01)){
			G_Card_Type = K_MEDIA_NANDF;
			G_ucStorageType = G_Card_Type;
			G_NandAlreadyMount |= 0x01;
			sp1kVfsInit(1);
		}
		G_Card_Type = type;
	}
#endif

	G_ucStorageType = G_Card_Type;

_appStorageMount_retry:
	devAttr = sp1kDevHdlGet();
	if( G_Card_Type == K_MEDIA_SDF ){
		appSdPowerRecycle();
		devAttr += DEV_ID_CARD;
	}
	else {
		devAttr += DEV_ID_DISK;
	}

	sts = sp1kVfsInit(1);
#ifndef DOS32_SUPPORT //eric for mantis #26173
        if( sts != TRUE && (G_DOS_Initial_Status == 3) && (G_Card_TotalCardSize > 2048) && (G_Card_Type == K_MEDIA_SDF)){
               osMsgPost(SP1K_MSG_CARD_NOT_SUPPORT);
			   IE = tmp;
			   return;
        }
#endif
	sp1kPbFileOrdertableInit();
	IE = tmp;
	//printf("%s,%d,G_Card_Type=%bx,%bx\n",__FILE__,__LINE__, G_Card_Type,G_DOS_Initial_Status);

	if( sts != TRUE ){
		//osMsgFlush();
		if (DOS_DosRamStsGet() == TRUE) {
			if ( G_Card_Type == K_MEDIA_DOSRAM && devAttr->devType == DEV_TYPE_DISK_DRAM) {
				printf("DosRam init fail!\n");
			}
		} else {
			if ( G_Card_Type == K_MEDIA_NANDF && devAttr->devType == DEV_TYPE_DISK_NAND) {
				printf("Nand init fail!\n");

				//add for mantis #36958 @start
				if(sp1kDiskTypeGet() != DEV_TYPE_DISK_SPI)
				{
					osMsgPost(SP1K_MSG_NAND_ERROR);
				}
				//start for mantis #36958 @end 
				
			} else {
				if(retry == 0 ) {
					retry++;
					goto _appStorageMount_retry;
				}
				if (!appSDPlugStatusGet()) {
					printf("Card init fail!\n");
					osMsgPost(SP1K_MSG_CARD_ERROR);
				} else {
					osMsgPost(SP1K_MSG_CARD_PLUG_OUT);
				}
			}
		}
	}

	storageReadyflag = SUCCESS;
}

//-----------------------------------------------------------------------------
//appTVUSBOutDetect
//-----------------------------------------------------------------------------
/**
 * @brief	detect tv plug in plug out
 * @param	none
 * @retval	none
 * @see
 * @author	jintao.liu
 * @since	2008-02-23
 * @todo
 * @bug
 * @note	in EVB,can not connect TV and usb together.
*/
extern UINT8 G_UI_USBConnect;
void appUSBOutDetect(void)
{
#if 0//zhenglei
	static UINT8 plugIn = 0xFF;
	static UINT8 usbStatus = 0xFF;
	static UINT8 time = 0;
	scanTag_t* pAdcHdl;
	UINT8 sts, msg;
	static UINT8 flg=0;

	if (pkgChipIdGet() == 0x1527){
		if(flg==0)sp1kUSB_PlugCfg();
	}
	if ( plugIn == sp1kUSB_PlugGet() ) {
		printf("zhenglei....usb...1\n");
		time++;
	}
	else {
		printf("zhenglei....usb...2\n");
		plugIn = sp1kUSB_PlugGet();
		time = 0;
		if (pkgChipIdGet() == 0x1527){
			if(flg==0)sp1kLED_BusyCfg();
		}
		return;
	}

	if ( time < 3 ) {
		if (pkgChipIdGet() == 0x1527){
			if(flg==0)sp1kLED_BusyCfg();
		}
		return;//detect 3 times to avoid dithering
	}
	printf("zhenglei....usb...plug in\n");
	sts = appCurrStateGet();
	if ( usbStatus != plugIn ) {
		if ( sts != APP_STATE_POWER_ON ) {
			usbStatus = plugIn;
		}
		if ( plugIn ) {  /* usb plug in. */
			if ( sts != APP_STATE_POWER_ON ) {
				//sp1kHalUSBSwPlugIn(); //software plug in
				sp1kTimeDelay1s();//wait about 1 second

				//disable battery detect function, force battery level to full
				sp1kBattEnable(DISABLE);
				sp1kAdcHdlGet(&pAdcHdl);
				pAdcHdl->battAdc.battLvl = POWER_BAT_FULL;
				uiUpdateBatteryLevel();
			}
			printf("zhenglei....usb...set msg = 0x42\n");
			msg = SP1K_MSG_USB_PLUG_IN;
		}
		else {  /* usb plug out. */
			if ( sts != APP_STATE_POWER_ON ) {
				G_UI_USBConnect = 0;
				sp1kBattEnable(ENABLE);
				//HAL_USBSwPlugOut();
				if(G_PCCAM ==1){
					G_PCCAM = 0;
					sp1kUsbPccamStop();
					TIMER0_Start();
				}
			}
			msg = SP1K_MSG_USB_PLUG_OUT;
		}

		osMsgPost(msg);
		if (pkgChipIdGet() == 0x1527){
			if(msg == SP1K_MSG_USB_PLUG_OUT){
				sp1kLED_BusyCfg();
				flg=0;
			}else {
				flg=1;
			}
		}
	}
	if (pkgChipIdGet() == 0x1527){
		if(flg == 0){
			sp1kLED_BusyCfg();
		}
	}
#endif
}

//-----------------------------------------------------------------------------
//appPowerCtrl
//-----------------------------------------------------------------------------
/**
 * @brief	appBattStsHandle
 * @param	none
 * @retval	none
 * @see
 * @author	phil.lin
 * @since	2008-02-23
 * @todo
 * @bug
 * @note
*/
UINT8 appBattStsHandle(void)
{
	powerBatLv_t batlv;

	appBatLvGet(&batlv);

	//battery empty flow
	if (batlv == POWER_BAT_BELOWEMPTY) {
#if BATT_LOW_PWR_OFF
		/*check if the power off process is running*/
		if (!sp1kPwrOffProcChk()) {
			/*if not, configure and start the process*/
			sp1kPwrOffCfg(1, BATT_LOW_PWR_OFF_DELAY);//5s
		}
#else
		uiUpdateOSDBatEmpty();
		//sp1kHalGPIOBitSet(PWR_ON_EN, 0);//power off
		osMsgPost(SP1K_MSG_POWER_OFF);
		sp1kBtnDisableAll();//ready to power off, disable all button!
#endif
	}

	return batlv;
}

//-----------------------------------------------------------------------------
//appModePowerCtrl
//-----------------------------------------------------------------------------
/**
 * @Power control for all mode
 * @param	Mode:
 * @retval	none
 * @see
 * @author	allen.lin
 * @since	2008-04-2
 * @todo
 * @bug
 * @note
*/
xdata UINT8 pwrCtrlParaBuf[512] _at_ 0x7200;
xdata UINT8 pwrCtrlParaBuf_s[10];
xdata appPwrCtrlPara_t* PwrCtrlPara;
UINT8 appModePowerCtrl(UINT8 Mode)
{
	#if (_PwrCtrlEn)
		UINT8 RLSB,RMSB;

		PwrCtrlPara = (appPwrCtrlPara_t*)&pwrCtrlParaBuf_s[0];
		M_DRAM_CardSetStartAddress((UINT32)(K_SDRAM_PwrCtrlParameterBuf + (Mode<<2)),1);
		M_DRAM_ReadWord(RLSB, RMSB);
		PwrCtrlPara->cpuclk = RLSB;
		PwrCtrlPara->dramclk = RMSB;
		M_DRAM_ReadWord(RLSB, RMSB);
		PwrCtrlPara->reg2013 = RLSB;
		PwrCtrlPara->reg2014 = RMSB;
		M_DRAM_ReadWord(RLSB, RMSB);
		PwrCtrlPara->reg2015 = RLSB;

		printf("@@mode=%bx\n",Mode);
		//PwrCtrlPara = pwrCtrlParaBuf + (Mode<<3);

		//printf("cpuclk=%2bx\n",PwrCtrlPara->cpuclk);
		//printf("dramclk=%2bx\n",PwrCtrlPara->dramclk);
		//printf("reg2013=%2bx\n",PwrCtrlPara->reg2013);
		//printf("reg2014=%2bx\n",PwrCtrlPara->reg2014);
		//printf("reg2015=%2bx\n",PwrCtrlPara->reg2015);

		#if 1
		sp1kHalPwrCtrl(PwrCtrlPara->cpuclk,\
					PwrCtrlPara->dramclk,\
					PwrCtrlPara->reg2013,\
					PwrCtrlPara->reg2014,\
					PwrCtrlPara->reg2015);
		#endif

	#else
		Mode = Mode;
	#endif
		XBYTE[0x2013] = 0xEF;
	//	XBYTE[0x2014] = 0xFD;
		XBYTE[0x2015] = 0xE7;	
	return SUCCESS;
}

void UI_UsbModeSet(UINT32 mode) USING_0
{
	switch( mode ){
/*
		case K_UISTATUS_USBMODE:
			G_UIStatus = K_UISTATUS_USBMODE;
			break;
*/			
		case K_UISTATUS_USBMODE_PCCAM:
			G_UIStatus = K_UISTATUS_USBMODE_PCCAM;
			break;
		case K_UISTATUS_USBMODE_MASS:
			G_UIStatus = K_UISTATUS_USBMODE_MASS;
			if (G_SDCardPlugInOut == 0x01){
				Card_InitRam();
				Card_InitGlobal();

				MLUN_Initialize();
				G_SDCardPlugInOut = 0x00;
			}
			break;
		default:
			break;
	}
}

#ifdef WHITE_LED
//an API to ctrl white LED
//if low light --> led on
//if high light --> led off
void appWhiteLedCtrl(void)
{
	UINT8 value;

	sp1kAeStatusGet(SP1K_AE_LowLight, &value);

	if (value == 1)
	{
		sp1kLED_SelfSet(0);
	}
	else
	{
		sp1kLED_SelfSet(1);
	}
}
#endif /*WHITE_LED*/

UINT8 appBGImgDec(UINT32 resId, struct Exif_Decompress_Parameter* pImgAttr, UINT32 srcAddr, UINT32 dstAddr, UINT8 bWait)
{
	UINT8 sts, opt;
	UINT32 size;
	struct Exif_Decompress_Parameter MainImgPara;

	/* load resource file */
	sp1kNandRsvRead(resId, srcAddr << 1);

	/* exif header parsing */
	sp1kNandRsvSizeGet(resId, NULL, &size);
	sts = exifParsingFile(srcAddr, size, 0, NULL, &MainImgPara, NULL);
	if (sts != TRUE) {
		//printf("exifParsingFile Fail\n");
		return FAIL;
	}

	/* check if wait vlc decode finished */
	if (bWait) {
		opt = 0x00;
	} else {
		opt = 0x08; /* hit and run */
	}

	/* check YUV format and if the vlc data is at odd address */
	if (MainImgPara.DataType == K_File_DataType_YUV420) {
		opt |= 0x05;
	} else if (MainImgPara.DataType == K_File_DataType_YUV422) {
		opt |= 0x04;
	}
	if (exifVlcAtOdd) {
		exifVlcAtOdd = 0;
		opt |= 0x10;
	}

	/* image decode process */
	sp1kHalJpegDecode(
		MainImgPara.Addr,
		MainImgPara.Width,
		MainImgPara.Height,
		dstAddr,
		0,
		opt,
		0
	);

	/* post param */
	if (pImgAttr) {
		pImgAttr->Width = MainImgPara.Width;
		pImgAttr->Height = MainImgPara.Height;
	}
	return SUCCESS;
}

